package com.xindacloud.sms.portal.controller;

import com.google.gson.Gson;
import com.xindacloud.sms.portal.component.SendNotifyMessageComponent;
import com.xindacloud.sms.portal.dto.SearchMessageDTO;
import com.xindacloud.sms.portal.dto.SmsSubmissionRecordDTO;
import com.xindacloud.sms.portal.dto.SubmitMessageDTO;
import com.xindacloud.sms.portal.entity.SmsUser;
import com.xindacloud.sms.portal.entity.SmsUserAllowOperator;
import com.xindacloud.sms.portal.exception.ServiceException;
import com.xindacloud.sms.portal.service.ISmsSubmissionRecordService;
import com.xindacloud.sms.portal.service.ISmsUserAllowOperatorService;
import com.xindacloud.sms.portal.service.ISmsUserService;
import com.xindacloud.sms.portal.utils.*;
import com.xindacloud.sms.portal.vo.CheckPhoneNumberVO;
import com.xindacloud.sms.portal.vo.SearchMessageVO;
import com.xindacloud.sms.portal.vo.ValidNumberResultVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.xindacloud.sms.portal.utils.UserSessionHelp.getUserFromSession;

@Api(tags = {"短信发送接口"})
@RestController
@RequestMapping(value = "/api/v1/portal/sms")
@Slf4j
public class SubmitMessageController {

    private final ISmsSubmissionRecordService smsSubmissionRecordService;

    private final ISmsUserService smsUserService;

    private final ISmsUserAllowOperatorService userAllowOperatorService;

    private final SendNotifyMessageComponent sendNotifyMessageComponent;


    @Autowired
    public SubmitMessageController(ISmsSubmissionRecordService smsSubmissionRecordService,
                                   ISmsUserService smsUserService,
                                   ISmsUserAllowOperatorService userAllowOperatorService,
                                   SendNotifyMessageComponent sendNotifyMessageComponent) {

        this.smsSubmissionRecordService = smsSubmissionRecordService;
        this.smsUserService = smsUserService;
        this.userAllowOperatorService = userAllowOperatorService;
        this.sendNotifyMessageComponent = sendNotifyMessageComponent;
    }

    @ApiOperation(value = "发送短信", response = UnionResultHelp.class)
    @PostMapping(value = "/send", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public UnionResultHelp submitMessage(@ApiParam(name = "submitMessageDTO", value = "发送短信", required = true)
                                         @RequestBody @Valid SubmitMessageDTO submitMessageDTO,
                                         HttpServletRequest request) {


        final SmsUser smsUser = (SmsUser) smsUserService.getUserDetail(getUserFromSession(request).getUserId());
        if (Objects.isNull(smsUser) || smsUser.getBalance() <= 0) {
            throw new ServiceException("账户余额不足", UnionResultHelp.StatusEnum.Fail.code());
        }

        final List<String> recipients = submitMessageDTO.getRecipientList();
        BigDecimal finalPrice = BigDecimal.ZERO;
        for (String recipient : recipients) {
            final CheckPhoneNumberVO phoneNumberVO = PhoneUtil.getPoneNumber(recipient);
            if (Objects.isNull(phoneNumberVO)) {
                throw new ServiceException("存在无效的号码:" + recipient, UnionResultHelp.StatusEnum.Fail.code());
            }
            final SmsUserAllowOperator smsUserAllowOperator = userAllowOperatorService.queryUserAllowOperatorMinPrice(smsUser.getUserId(),
                    phoneNumberVO.getRegion(), String.valueOf(phoneNumberVO.getCountryPrefix()));
            final BigDecimal messagePrice = UserSessionHelp.calcMessagePrice(smsUserAllowOperator.getPrice(),
                    submitMessageDTO.getMessageCount());
            finalPrice = finalPrice.add(messagePrice);
            if (smsUser.getBalance() < finalPrice.doubleValue()) {
                throw new ServiceException("账户余额不足,不足以抵扣当前短信费用,请先充值.", UnionResultHelp.StatusEnum.Fail.code());
            }
        }
        log.info("###WEB端发送短信参数:{}", new Gson().toJson(submitMessageDTO));
        try {
            final Map<String, Object> map = sendNotifyMessageComponent.sendNotifyMessage(submitMessageDTO, smsUser.getUsername(), smsUser.getPassword());
            return UnionResultHelp.builder()
                    .message("提交短信成功.")
                    .status(UnionResultHelp.StatusEnum.Success.code())
                    .data(map)
                    .timestamp(UnionResultHelp.getStrTimestamp())
                    .build();
        } catch (Exception e) {
            return UnionResultHelp.builder()
                    .message("提交短信失败.")
                    .status(UnionResultHelp.StatusEnum.Fail.code())
                    .data(null)
                    .timestamp(UnionResultHelp.getStrTimestamp())
                    .build();
        }
    }


    private UnionResultHelp sendNotifyMessage2Sqs(SubmitMessageDTO submitMessageDTO, String username, String password) {

        try {
            final Map<String, Object> map = sendNotifyMessageComponent.sendNotifyMessage(submitMessageDTO, username, password);
            return UnionResultHelp.builder()
                    .message("提交短信成功.")
                    .status(UnionResultHelp.StatusEnum.SUBMIT_SUCCESS.code())
                    .data(map)
                    .timestamp(UnionResultHelp.getStrTimestamp())
                    .build();
        } catch (Exception e) {

            return UnionResultHelp.builder()
                    .message("提交短信失败.")
                    .status(UnionResultHelp.StatusEnum.SUBMIT_FAILED.code())
                    .data(null)
                    .timestamp(UnionResultHelp.getStrTimestamp())
                    .build();
        }

    }

    @ApiOperation(value = "开放API提交短信至队列", response = UnionResultHelp.class)
    @PostMapping(value = "/open/submit", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public UnionResultHelp openApiSubmitMessage(@ApiParam(name = "submitMessageDTO", value = "发送短信", required = true)
                                                @RequestBody @Valid SubmitMessageDTO submitMessageDTO,
                                                @ApiParam(name = "username", value = "用户名", required = true)
                                                @RequestHeader(name = "username") String username,
                                                @ApiParam(name = "password", value = "密码", required = true)
                                                @RequestHeader(name = "password") String password) {


        if (Objects.isNull(submitMessageDTO)) {
            return UnionResultHelp.builder()
                    .message("无效的请求参数.")
                    .status(UnionResultHelp.StatusEnum.INVALID_PARAMETERS.code())
                    .timestamp(UnionResultHelp.getStrTimestamp())
                    .isValid(false)
                    .build();
        }

        if (CollectionUtils.isEmpty(submitMessageDTO.getRecipientList())
                || StringUtils.isEmpty(submitMessageDTO.getMessageBody())
                || StringUtils.isEmpty(submitMessageDTO.getSender())
                || StringUtils.isEmpty(submitMessageDTO.getSmsType())
                || StringUtils.isEmpty(username)
                || StringUtils.isEmpty(password)) {
            return UnionResultHelp.builder()
                    .message("缺少一个或多个必要的参数.")
                    .status(UnionResultHelp.StatusEnum.MISSING_PARAMETERS.code())
                    .timestamp(UnionResultHelp.getStrTimestamp())
                    .isValid(false)
                    .build();
        }


        log.info("###开放API提交短信参数为:{}", new Gson().toJson(submitMessageDTO));
        final SmsUser smsUser = smsUserService.queryUserInfoFor(username, password);
        if (Objects.isNull(smsUser)) {
            return UnionResultHelp.builder()
                    .message("无效的认证,您提供的username/password无效或被禁用.")
                    .status(UnionResultHelp.StatusEnum.INVALID_CREDENTIALS.code())
                    .timestamp(UnionResultHelp.getStrTimestamp())
                    .isValid(false)
                    .build();
        }

        if (smsUser.getBalance() <= 0) {
            return UnionResultHelp.builder()
                    .message("您没有足够的余额发送消息.充值并重试.")
                    .status(UnionResultHelp.StatusEnum.INSUFFICIENT_BALANCE.code())
                    .timestamp(UnionResultHelp.getStrTimestamp())
                    .isValid(false)
                    .build();
        }

        final List<String> recipients = submitMessageDTO.getRecipientList();
        BigDecimal finalPrice = BigDecimal.ZERO;
        for (String recipient : recipients) {
            final CheckPhoneNumberVO phoneNumberVO = getCheckPhoneNumberVO(recipient);
            if (Objects.isNull(phoneNumberVO)) {
                return UnionResultHelp.builder()
                        .message("无效的手机号码:" + recipient)
                        .status(UnionResultHelp.StatusEnum.INVALID_RECIPIENT.code())
                        .timestamp(UnionResultHelp.getStrTimestamp())
                        .isValid(false)
                        .build();
            }
            try {
                final SmsUserAllowOperator allowOperator = userAllowOperatorService.queryUserAllowOperatorMinPrice(smsUser.getUserId(),
                        phoneNumberVO.getRegion(), String.valueOf(phoneNumberVO.getCountryPrefix()));
                finalPrice = finalPrice.add(UserSessionHelp.calcMessagePrice(allowOperator.getPrice(),
                        CommonUtils.calcMessageCount(submitMessageDTO.getMessageBody())));
                if (smsUser.getBalance() < finalPrice.doubleValue()) {
                    return UnionResultHelp.builder()
                            .message("您没有足够的余额发送消息.充值并重试.")
                            .status(UnionResultHelp.StatusEnum.INSUFFICIENT_BALANCE.code())
                            .timestamp(UnionResultHelp.getStrTimestamp())
                            .isValid(false)
                            .build();
                }
            } catch (Exception e) {
                if (e instanceof ServiceException) {
                    return UnionResultHelp.builder()
                            .message("您未同步价格,请联系销售经理同步价格")
                            .status(UnionResultHelp.StatusEnum.PRICING_LIST_EMPTY.code())
                            .timestamp(UnionResultHelp.getStrTimestamp())
                            .isValid(false)
                            .build();
                }
            }
        }

        return sendNotifyMessage2Sqs(submitMessageDTO, smsUser.getUsername(), smsUser.getPassword());

    }


    @ApiOperation(value = "提供给YY开放API提交短信至队列", response = UnionResultHelp.class)
    @PostMapping(value = "/open/submit/yy", produces = MediaType.APPLICATION_JSON_VALUE)
    public Map<String, Object> openApiSubmitMessage(HttpServletRequest request) {
        final Map<String, String[]> parameterMap = request.getParameterMap();

        if (Objects.isNull(parameterMap)) {
            return CommonUtils.buildYYResult(UnionResultHelp.StatusEnum.INVALID_PARAMETERS.code(), "无效的请求参数.", "");
        }

        final String pwd = request.getParameter("pwd");
        final String account = request.getParameter("account");
        final String cbkUrl = request.getParameter("cbkUrl");
        final String sign = StringUtils.defaultString(request.getParameter("sign"), "");
        final String senderId = request.getParameter("senderId");
        final String content = request.getParameter("content");
        final String p_mobile = request.getParameter("mobile");
        final String language = request.getParameter("language");
        final String extend = request.getParameter("extend");
        if (StringUtils.isEmpty(p_mobile)
                || StringUtils.isEmpty(content)
                || StringUtils.isEmpty(senderId)
                || StringUtils.isEmpty(cbkUrl)
                || StringUtils.isEmpty(account)
                || StringUtils.isEmpty(pwd)) {

            return CommonUtils.buildYYResult(UnionResultHelp.StatusEnum.MISSING_PARAMETERS.code(), "缺少一个或多个必要的参数.", "");
        }


        log.info("###YY开放API提交短信参数为:{}", new Gson().toJson(parameterMap));
        final String password = CommonUtils.encodeMD5(pwd.trim());
        final SmsUser smsUser = smsUserService.queryUserInfoFor(account.trim(), password);
        if (Objects.isNull(smsUser)) {
            return CommonUtils.buildYYResult(UnionResultHelp.StatusEnum.INVALID_CREDENTIALS.code(),
                    "无效的认证,您提供的account/pwd.", "");
        }

        if (smsUser.getBalance() <= 0) {

            return CommonUtils.buildYYResult(UnionResultHelp.StatusEnum.INSUFFICIENT_BALANCE.code(),
                    "您没有足够的余额发送消息.充值并重试.", "");
        }

//        String mobile = p_mobile.trim().startsWith("00") ? p_mobile.trim().replace("00", "") : p_mobile;
        String mobile = p_mobile.trim().startsWith("00") ? p_mobile.trim().substring(2, p_mobile.length()) : p_mobile;

        final List<String> recipients = Arrays.asList(mobile);
        BigDecimal finalPrice = BigDecimal.ZERO;
        for (String recipient : recipients) {
            final CheckPhoneNumberVO phoneNumberVO = getCheckPhoneNumberVO(recipient);
            if (Objects.isNull(phoneNumberVO)) {
                return CommonUtils.buildYYResult(UnionResultHelp.StatusEnum.INVALID_RECIPIENT.code(),
                        "无效的手机号码: " + recipient, "");
            }
            try {
                final SmsUserAllowOperator allowOperator = userAllowOperatorService.queryUserAllowOperatorMinPrice(smsUser.getUserId(),
                        phoneNumberVO.getRegion(), String.valueOf(phoneNumberVO.getCountryPrefix()));
                finalPrice = finalPrice.add(UserSessionHelp.calcMessagePrice(allowOperator.getPrice(),
                        CommonUtils.calcMessageCount(content)));
                if (smsUser.getBalance() < finalPrice.doubleValue()) {
                    return CommonUtils.buildYYResult(UnionResultHelp.StatusEnum.INSUFFICIENT_BALANCE.code(),
                            "您没有足够的余额发送消息.充值并重试.", "");
                }
            } catch (Exception e) {
                if (e instanceof ServiceException) {
                    return CommonUtils.buildYYResult(UnionResultHelp.StatusEnum.PRICING_LIST_EMPTY.code(),
                            "您未同步价格,请联系销售经理同步价格.", "");
                }
            }
        }

        final SubmitMessageDTO submitMessageDTO = new SubmitMessageDTO();
        submitMessageDTO.setMessageBody(content);
        submitMessageDTO.setCbkUrl(cbkUrl);
        submitMessageDTO.setRecipientList(recipients);
        submitMessageDTO.setSender(senderId);
        submitMessageDTO.setSign(sign);
        submitMessageDTO.setLanguage(language);
        submitMessageDTO.setExtend(extend);
        submitMessageDTO.setSmsType("singe");

        smsUserService.updateUserTextPassword(account.trim(), pwd.trim());

        final UnionResultHelp resultHelp = sendNotifyMessage2Sqs(submitMessageDTO, smsUser.getUsername(), smsUser.getPassword());
        final Object data = resultHelp.getData();
        if (Objects.nonNull(data)) {
            Map<String, Object> rsMap = (Map<String, Object>) data;
            if (MapUtils.isNotEmpty(rsMap)) {
                final String messageId = rsMap.get("messageId").toString();
                return CommonUtils.buildYYResult(UnionResultHelp.StatusEnum.SUBMIT_SUCCESS.code(), "", messageId);
            }

        }
        return CommonUtils.buildYYResult(UnionResultHelp.StatusEnum.SUBMIT_FAILED.code(), "提交短信异常.", "");
    }


    private CheckPhoneNumberVO getCheckPhoneNumberVO(String recipient) {
        try {
            return PhoneUtil.getPoneNumber(recipient);
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    @ApiOperation(value = "查询短信", response = SearchMessageVO.class)
    @PostMapping(value = "/search", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public Object searchMessage(@ApiParam(name = "searchMessageDTO", value = "查询短信", required = true)
                                @RequestBody @Valid SearchMessageDTO searchMessageDTO,
                                HttpServletRequest request) {

        searchMessageDTO.setUserId(getUserFromSession(request).getUserId().toString());
        return smsSubmissionRecordService.searchMessage(searchMessageDTO);
    }


    @ApiOperation(value = "群发导入号码支持格式为csv,excel", notes = "返回200为修改成功,其他返回码均为异常")
    @PostMapping(value = "/import-recipient")
    public Object importRecipient(@ApiParam(name = "file", value = "群发导入号码,支持格式为csv,excel", required = true)
                                  @RequestParam("file") MultipartFile file, HttpServletRequest request) {
        final List<String> recipients = ImportRecipientUtil.importRecipient(file);
        //有效号码
        final List<String> validRecipientList = recipients.stream()
                .filter(PhoneUtil::checkPhoneNumber)
                .collect(Collectors.toList());
        //无效号码
        final List<String> invalidRecipientList = recipients.stream()
                .filter(rs -> !validRecipientList.contains(rs))
                .collect(Collectors.toList());

        return ValidNumberResultVO.builder()
                .invalidRecipientList(invalidRecipientList)
                .invalidCount(invalidRecipientList.size())
                .validRecipientList(validRecipientList)
                .validCount(validRecipientList.size())
                .totalCount(validRecipientList.size())
                .build();

    }

    @ApiOperation(value = "短信dashboard报告列表")
    @PostMapping(value = "/getSmsDashBoardList")
    public Object getSmsDashBoardList(@RequestBody SmsSubmissionRecordDTO smsSubmissionRecordDTO, HttpServletRequest request) {
        smsSubmissionRecordDTO.setUserId(getUserFromSession(request).getUserId());
        return smsSubmissionRecordService.getSmsDashBoardList(smsSubmissionRecordDTO);
    }
}
